package com.qd.admin.controller.dict;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.ApiResultWrapper;
import com.cdqidi.dto.DelDTO;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.page.PageUtil;
import com.cdqidi.valid.group.DefaultGroup;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qd.common.sys.annotation.OperatorInfo;
import com.qd.common.sys.domain.entity.dict.DictDataDTO;
import com.qd.common.sys.enums.OperatorType;
import com.qd.core.service.InitSyncService;
import com.qd.system.service.dict.DictDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 数据字典
 *
 * @author sjk
 */
@RestController
@Validated
@Slf4j
@RequiredArgsConstructor
public class DictDataController {
    private final ObjectMapper objectMapper;
    private final DictDataService dictDataService;
    private final InitSyncService initSyncService;


    /**
     * 新增码表数据
     *
     * @return 新增数据
     */
    @PreAuthorize("@ps.hasPermission('system:dict:table:save')")
    @PostMapping(value = "/sys/sysDictData/save")
    @OperatorInfo(title = "添加码表", operator = OperatorType.INSERT)
    public DictDataDTO save(@Validated(DefaultGroup.class) @RequestBody DictDataDTO dictDataDto) {
        dictDataDto.setAddTime(LocalDateTime.now());
        return dictDataService.save(dictDataDto);
    }

    /**
     * 修改码表数据
     *
     * @return true or false
     */
    @PreAuthorize("@ps.hasPermission('system:dict:table:edit')")
    @PutMapping(value = "/sys/sysDictData/update")
    @OperatorInfo(title = "更新码表", operator = OperatorType.UPDATE)
    public ApiResultWrapper<Object> update(@Validated({DefaultGroup.class}) @RequestBody DictDataDTO dictDataDto) {
        dictDataService.update(dictDataDto);
        return ApiResult.success("修改成功");
    }

    /**
     * 删除码表数据
     */
    @PreAuthorize("@ps.hasPermission('system:dict:table:delete')")
    @DeleteMapping(value = "/sys/sysDictData/delete")
    @OperatorInfo(title = "删除码表", operator = OperatorType.DELETE)
    public ApiResultWrapper<Object> delete(@Validated @RequestBody DelDTO<String> delDTO) {
        final List<String> ids = delDTO.getIds();
        if (ids.size() == 1) {
            dictDataService.removeById(ids.get(0));
        } else {
            dictDataService.removeBatchIds(ids);
        }
        return ApiResult.success();
    }

    /**
     * 码表数据详情
     *
     * @return 列表
     */
    @GetMapping(value = "/sys/sysDictData/getById")
    public DictDataDTO getById(@Validated @NotBlank(message = DelDTO.ID_NULL_MSG) String id) {
        return dictDataService.getByIdDto(id);
    }

    /**
     * 码表数据列表
     *
     * @return 列表
     */
    @GetMapping(value = "/sys/sysDictData/page")
    public IPage<DictDataDTO> page(DictDataDTO dictDataDto) {
        return dictDataService.page(PageUtil.buildPage(dictDataDto), dictDataDto);
    }

    /**
     * 清空缓存
     */
    @PreAuthorize("@ps.hasPermission('system:sysDictData:clearCache')")
    @DeleteMapping(value = "/sys/sysDictData/clearCache")
    @OperatorInfo(title = "清空码表缓存", operator = OperatorType.CLEAN)
    public ApiResultWrapper<Object> clearCache(@RequestBody(required = false) Map<String, List<String>> map) {
        if (null == map || map.isEmpty()) {
            dictDataService.clearCacheAll();
            return ApiResult.success("清空全部载缓存成功");
        } else {
            final List<String> ids = map.get("ids");
            if (null == ids || ids.isEmpty()) {
                return ApiResult.error("类型ID不能为空");
            }
            ids.forEach(dictDataService::clearCacheByTypeId);
            return ApiResult.success("清空部分缓存成功");
        }
    }

    /**
     * 加载缓存
     *
     * @return 列表
     */
    @PreAuthorize("@ps.hasPermission('system:dict:loadCache')")
    @GetMapping(value = "/sys/sysDictData/loadCache")
    @OperatorInfo(title = "加载码表缓存", operator = OperatorType.OTHER)
    public ApiResultWrapper<String> loadCache(String ids) {
        log.info("加载码表缓存: {}", ids);
        if (StringUtils.hasLength(ids)) {
            try {
                final List<String> types = objectMapper.readValue(ids, new TypeReference<>() {
                });
                if (null == types || types.isEmpty()) {
                    initSyncService.initDictData();
                    return ApiResult.success("加载全量缓存成功");
                } else {
                    types.forEach(typeId -> {
                        dictDataService.clearCacheByTypeId(typeId);
                        dictDataService.getListByType(typeId);
                    });
                    return ApiResult.success("加载部分缓存成功");
                }
            } catch (JsonProcessingException e) {
                log.info("参数格式错误,ids: {}",ids);
                throw new ApiException("参数格式错误");
            }
        } else {
            initSyncService.initDictData();
            return ApiResult.success("加载全量缓存成功");
        }
    }

    /**
     * 按分类查询码表
     *
     * @param ids 分类信息
     * @return 码表集合
     */
    @GetMapping(value = "/sys/sysDictData/getListByTypes")
    public Map<String, Object> getListByTypes(@Validated @NotBlank(message = "ids不能为空") String ids) {
        log.info("按分类查询码表: {}", ids);
        try {
            final List<String> types = objectMapper.readValue(ids, new TypeReference<>() {
            });
            if (null == types || types.isEmpty()) {
                throw new ApiException("types不能为空");
            }
            return dictDataService.getListByTypes(types);
        } catch (JsonProcessingException e) {
            log.info("参数格式错误,ids: {}", ids);
            throw new ApiException("参数格式错误");
        }
    }

    /**
     * 导出
     *
     * @param query 查询参数
     */
    @PreAuthorize("@ps.hasPermission('system:dict:table:export')")
    @GetMapping(value = "/sys/sysDictData/export")
    public void export(DictDataDTO query) throws IOException {
        long startTime = System.currentTimeMillis();
        dictDataService.export(query);
        long endTime = System.currentTimeMillis();
        log.info("数据字典导出,总耗时: {}s", (endTime - startTime) / 1000);
    }

}